﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Collections.Generic;

namespace Crypt_Tranceiver
{

    public class StateObject
    {
        // 客户socket 
        public Socket workSocket = null;
        // 接受buffer大小   
        public const int BufferSize = 2048;
        // 接收buffer   
        public byte[] buffer = new byte[BufferSize];
        // 接受到的数据  
        public StringBuilder sb = new StringBuilder();
    }

    //异步服务端类
    public class AsynchronousSocketListener
    {  
        public static Socket listener;
        public static IPEndPoint localEndPoint;

        //客户端维护列表和互斥量
        public static Mutex client_list_mutex;
        public static List<StateObject> client_list;

        private static StateObject state;

        public AsynchronousSocketListener()
        {
            
        }
        public static void StartListening(int port)
        {   
            byte[] bytes = new Byte[1024];
            localEndPoint = new IPEndPoint(IPAddress.Any, port); //监听本机所有地址 
            listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                //绑定并监听本地端口
                listener.Bind(localEndPoint);
                listener.Listen(100);
                //启动异步套接字监听连接
                Console.WriteLine("等待客户端的连接...");
                listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
                //通知主线程，已经开始监听指定端口
                work_list status = new work_list();
                status.Oper = work_list.SERVER_START;
                status.Req_Res = work_list.DIR_RES;
                status.Date = listener.LocalEndPoint.ToString();
                status.Length = status.Date.Length;
                status.Error = work_list.ERROR_OK;
                status.Direction = work_list.DIR_OUT;
                Form_Main.status_mutex.WaitOne();
                Form_Main.status_inlist.Enqueue(status);
                Form_Main.status_mutex.ReleaseMutex();
                client_list = new List<StateObject>();
                client_list_mutex = new Mutex();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public static void StopListening()
        {
            try
            {
                //通知主线程已经结束端口的监听
                work_list status = new work_list();
                status.Oper = work_list.SERVER_STOP;
                status.Req_Res = work_list.DIR_RES;
                status.Date = listener.LocalEndPoint.ToString();
                status.Length = status.Date.Length;
                status.Error = work_list.ERROR_OK;
                status.Direction = work_list.DIR_OUT;
                Form_Main.status_mutex.WaitOne();
                Form_Main.status_inlist.Enqueue(status);
                Form_Main.status_mutex.ReleaseMutex();
                //结束监听
                listener.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public static void AcceptCallback(IAsyncResult ar)
        {   
            Socket listener = (Socket)ar.AsyncState;
            try
            {
                Socket handler = listener.EndAccept(ar);
                // 创建连接的维护数据，并将连接放入客户端队列中进行管理  
                state = new StateObject();
                state.workSocket = handler;
                client_list_mutex.WaitOne();
                client_list.Add(state);
                client_list_mutex.ReleaseMutex();
                //通知主线程有新的客户端连接传入
                work_list status = new work_list();
                status.Oper = work_list.CLIENT_ACCEPT;
                status.Req_Res = work_list.DIR_REQ;
                status.Date = state.workSocket.RemoteEndPoint.ToString();
                status.Length = status.Date.Length;
                status.Error = work_list.ERROR_OK;
                status.Direction = work_list.DIR_OUT;
                Form_Main.status_mutex.WaitOne();
                Form_Main.status_inlist.Enqueue(status);
                Form_Main.status_mutex.ReleaseMutex();
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                //启动异步套接字监听连接
                listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public static void ReadCallback(IAsyncResult ar)
        {
            String content = String.Empty;  
            StateObject state = (StateObject)ar.AsyncState;
            Socket handler = state.workSocket;
            try
            {
                // 从socket中读取数据  
                int bytesRead = handler.EndReceive(ar);
                if (bytesRead > 0)
                {
                    byte[] buff = new byte[2048];
                    //对收到的数据进行类型转换
                    content = Encoding.UTF8.GetString(state.buffer, 0, bytesRead);
                    //启动异步接受数据，注册接收回调函数
                    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                    work_list item = new work_list();
                    //对数据包进行解码
                    item = Form_Main.bg_message_decode(content);
                    //通知主线程有新的数据收到
                    Form_Main.tcp_in_mutex.WaitOne();
                    Form_Main.tcp_inlist.Enqueue(item);
                    Form_Main.tcp_in_mutex.ReleaseMutex();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

        }

        public static void Send(Socket handler, String data)
        {
            // 使用UTF8编码将string数据转化为byte   
            byte[] byteData = Encoding.UTF8.GetBytes(data);
            // 开始发送数据  
            try
            {
                handler.BeginSend(byteData, 0, byteData.Length, 0,
                    new AsyncCallback(SendCallback), handler);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                // 获取socket   
                Socket handler = (Socket)ar.AsyncState;
                // 完成数据发送  
                int bytesSent = handler.EndSend(ar);
                Console.WriteLine("Sent {0} bytes to client {1}.", bytesSent, handler.RemoteEndPoint.ToString());
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}